package cn.dslcode.security.config.security;

import cn.dslcode.common.web.WebUtil;
import cn.dslcode.common.web.response.CommonResponseCode;
import cn.dslcode.common.web.response.RestResponse;
import cn.dslcode.security.common.CaptchaAuthenticationException;
import cn.dslcode.security.common.DataCenter;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author dongsilin
 * @version 2018/4/11.
 */
@Slf4j
@Data
@Component
public class CustomAuthenticationHandlers {

    @Autowired
    private CustomSecurityConstant securityConstant;

    /**
     * 登陆成功后的处理
     */
    private AuthenticationSuccessHandler authenticationSuccessHandler;
    /**
     * 登陆失败后的处理
     */
    private AuthenticationFailureHandler authenticationFailureHandler;
    /**
     * 登出成功后的处理
     */
    private LogoutSuccessHandler logoutSuccessHandler;
    /**
     * 待认证处理
     */
    private AuthenticationEntryPoint authenticationEntryPoint;
    /**
     * 权限不通过处理
     */
    private AccessDeniedHandler accessDenyHandler;


    @PostConstruct
    public void init() {

        this.authenticationSuccessHandler = new SimpleUrlAuthenticationSuccessHandler() {
            @Override
            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
                log.info("*******************AuthenticationSuccessHandler");
                // 把认证信息缓存下来，方便踢人，修改他人权限
                DataCenter.authenticationMap.put(((UserDetails) authentication.getPrincipal()).getUsername(), authentication);
                WebUtil.output(response, RestResponse.buildSuccess(), WebUtil.ResponseOutputType.JSON);
            }
        };

        this.authenticationFailureHandler = new SimpleUrlAuthenticationFailureHandler() {
            @Override
            public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
                log.info("*******************AuthenticationFailureHandler");
                if (e instanceof CaptchaAuthenticationException) {
                    WebUtil.output(response, RestResponse.buildFail(e.getMessage()), WebUtil.ResponseOutputType.JSON);
                } else if (e instanceof UsernameNotFoundException) {
                    WebUtil.output(response, RestResponse.buildFail("用户名不存在"), WebUtil.ResponseOutputType.JSON);
                } else if (e instanceof BadCredentialsException) {
                    WebUtil.output(response, RestResponse.buildFail("密码错误"), WebUtil.ResponseOutputType.JSON);
                } else {
                    WebUtil.output(response, RestResponse.buildFail("操作失败"), WebUtil.ResponseOutputType.JSON);
                }
            }
        };

        this.logoutSuccessHandler = new SimpleUrlLogoutSuccessHandler() {
            @Override
            public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                log.info("*******************LogoutSuccessHandler");
                // 清除认证信息缓存
                if (!DataCenter.authenticationMap.isEmpty() && authentication != null) {
                    DataCenter.authenticationMap.remove(((UserDetails) authentication.getPrincipal()).getUsername());
                }
                WebUtil.output(response, RestResponse.buildSuccess(), WebUtil.ResponseOutputType.JSON);
            }
        };

        this.authenticationEntryPoint = (request, response, e) -> {
            if (WebUtil.isAjax(request)) {
                WebUtil.output(response, RestResponse.build(CommonResponseCode.UNAUTHENTICATION), WebUtil.ResponseOutputType.JSON);
                return;
            }
            response.sendRedirect(securityConstant.getUri().getLoginForm());
        };

        this.accessDenyHandler = (request, response, accessDeniedException) -> {
            if (WebUtil.isAjax(request)) {
                WebUtil.output(response, RestResponse.build(CommonResponseCode.UNAUTHORIZATION), WebUtil.ResponseOutputType.JSON);
                return;
            }
            response.sendRedirect(securityConstant.getUri().getUnauthorized());
        };

    }

}
